package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"strconv"
	"strings"

	_ "github.com/go-sql-driver/mysql"
)

var db *sql.DB

func initializeDatabase() (err error) {
	//data source name
	//用户名@密码@协议(ip:port)/数据库
	dsn := "root:PENCS*3768SJ@tcp(9.135.220.143:3306)/db_teg_abolish?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = sql.Open("mysql", dsn)
	if err != nil {
		return
	}

	//资源释放
	//defer db.Close()

	//尝试建立连接
	if err = db.Ping(); err != nil {
		fmt.Println("connect 2 database failed...")
		return
	}
	//最大连接数
	db.SetMaxOpenConns(10)
	//最大闲置连接数
	db.SetMaxIdleConns(10)
	return nil
}

var SvrClassMap = map[string]string{
	"计算逻辑型":   "CL",
	"热存储型":    "ST_H",
	"温存储型":    "ST_W",
	"冷存储型":    "ST_C",
	"大数据型":    "BI",
	"GPU型CVM": "GPU_CVM",
	"GPU算力":   "GPU_CP",
	"高IO型":    "IO_H",
	"其他":      "OTH",
	"总计":      "TOT",
}

// TbRoleDisplace 权限控制
type TbRoleDisplace struct {
	Id            int32  `gorm:"id"`
	RoleId        int32  `gorm:"role_id"`
	RoleSign      string `gorm:"role_sign"`
	RoleEnName    string `gorm:"role_en_name"`
	Privilege     string `gorm:"privilege"`
	PrivilegeSign string `gorm:"privilege_sign"`
}

// RolePrivilege TbRoleDisplace的Privilege字段结构
type RolePrivilege struct {
	//Query-查询权限; Update Delete    Insert-只和表(key)关联; key-表名, value-表(字段)权限
	Query map[string]*TablePrivilege
}

type TablePrivilege struct {
	//All-当前表所有权限() Part-部分权限
	Scope string
	//条件组
	WhereCond []*WhereCondition
}

type WhereCondition struct {
	//AND IN OR
	Operator string
	ParamKey string
	ParamVal interface{}
	//递归(子条件组)
	//WhereCond []*WhereCondition
}

func insertSourceRow(paramSplit []string) {
	sqlStr := "INSERT INTO tb_role_displace (role_id, role_sign, role_en_name, privilege_sign, privilege)" +
		"VALUES(?, ?, ?, ?, ?);"
	res, err := db.Exec(sqlStr, paramSplit[0], paramSplit[1], paramSplit[5], getPrivilegeSign(paramSplit[2], paramSplit[3], paramSplit[4]),
		CreatePrivilege(paramSplit[2], paramSplit[3], paramSplit[4]))
	if err != nil {
		log.Printf("update failed err : %v\n", err)
	}
	affectedNum, err := res.RowsAffected()
	if err != nil {
		log.Printf("update RowsAffected failed err : %v\n", err)
	}
	log.Println("受影响的行数=", affectedNum)
}

//直接传递sql进行执行, 效率偏低, 且存在sql注入问题
func main() {
	if err := initializeDatabase(); err != nil {
		panic(err)
	}
	fmt.Println("connected")

	//fmt.Println(CreatePrivilege("TX", "Test", ""))
	readAuthorityFile()

}

func getPrivilegeSign(bg, bizPath, planProduct string) string {
	var privilegeSign string
	if bg != "" {
		privilegeSign = bg
	}
	if bizPath != "" {
		privilegeSign = privilegeSign + "-" + bizPath
	}
	if planProduct != "" {
		privilegeSign = privilegeSign + "-" + planProduct
	}
	return privilegeSign
}

func CreatePrivilege(bg, bizPath, planProduct string) string {
	conditions := []*WhereCondition{
		{
			Operator: "AND",
			ParamKey: "bg",
			ParamVal: bg,
		}, {
			Operator: "AND",
			ParamKey: "biz_dept",
			ParamVal: bizPath,
		},
	}
	if planProduct != "" {
		conditions = append(conditions, &WhereCondition{
			Operator: "AND",
			ParamKey: "plan_product",
			ParamVal: planProduct,
		})
	}
	privilege := RolePrivilege{
		Query: map[string]*TablePrivilege{
			"tb_device_displace": {
				Scope:     "Part",
				WhereCond: conditions,
			},
		},
	}

	/*p := RolePrivilege{}
	err := JsonToStruct(StructToJson(privilege), &p)
	if err == nil {
		fmt.Println("JsonToStruct = ", p.Query["tb_device_displace"].WhereCond[0].Param["biz_path"])
	}*/
	return StructToJson(privilege)
}

func StructToJson(s interface{}) string {
	str, _ := json.Marshal(s)
	return string(str)
}

// json字符串转对象
func JsonToStruct(input string, output interface{}) error {
	return json.Unmarshal([]byte(input), output)
}

func readAuthorityFile() map[string]string {
	recordMap := map[string]string{}
	const filename = "D:\\code\\go\\go-learn\\go-project\\mysql-read-file\\authority.txt"
	if contents, err := ioutil.ReadFile(filename); err == nil {
		recordStr := string(contents)
		paramLine := strings.Split(recordStr, "\r\n")
		for _, str := range paramLine {
			paramSplit := strings.Split(str, ",")
			fmt.Println(paramSplit)
			insertSourceRow(paramSplit)
		}
	} else {
		fmt.Println("print file err: ", err)
	}
	return recordMap
}

func parseStrToInt(str string) int {
	if str != "" {
		tmpInt64, _ := strconv.ParseInt(str, 10, 64)
		return int(tmpInt64)
	}
	return 0
}
